<template>
	<view>
		<view>
			<view class="container-top-time">
				<view class="content-top-time">{{ currentTime }}</view>
			</view>
			<view class="container-tag-list">
				<scroll-view class="content-tag-list" enhanced :show-scrollbar="false" scroll-y>
					<view class="content-tag-item" v-for="(item, index) in tagList" :key="index">
						<span class="content-tag-item-child-index">{{ tagList.length - index }}</span>
						<span class="content-tag-item-child-time">{{ item }}</span>
						<van-icon class="content-tag-item-child-remove" name="cross" @click="removeTag(index)" />
					</view>
				</scroll-view>
			</view>
			<view class="container-play-component">
				<!-- 标记时间 -->
				<van-button @click="tag" round type="default">
					<van-icon name="flag-o" />
				</van-button>
				<!-- 录音&暂停 -->
				<van-button v-show="status === 0 || status === 2" @click="start" class="my-button-play-component-main" round type="default">
					<van-icon class="my-button-play-component-play" name="music"  />
				</van-button>
				<van-button v-show="status === 1" @click="pause" class="my-button-play-component-main" round type="default">
					<van-icon name="pause-circle" />
				</van-button>
				<!-- 停止保存 -->
				<van-button @click="stop" class="my-button-play-component-save" round type="default">
					<van-icon name="checked" />
				</van-button>
			</view>
			<!-- 底部弹出, @click-overlay="popupBottomPopupView" 监听点击蒙层部分 -->
			<van-popup 
				v-model:show="showBottomPopupView" 
				position="bottom" 
				round
				@after-leave="popupViewHideListener"
				>
				<view class="popup-bottom">
					<view class="popup-save-title">保存录音</view>
					<view>
						<!-- VantUI 这个双向绑定值，有 BUG 不能绑定，直接调用引用获取，最后的清空用 v-if 销毁和创建 -->
						<van-field
							v-if="showBottomPopupInputView"
						    clearable
						    label="备注"
						    left-icon="smile-o"
						    placeholder="输入录音备注"
							label-align="center"
							border
							class="my-field"
							ref="inputAudioFileName"
						/>
					</view>
					<view class="popup-bottom-play-container">
						<!-- 重置录音 -->
						<van-button @click="resetAudio" :disabled="playAudioStatus === 0" class="my-button-radius my-button-radius-replay" round type="default">
							<van-icon class="my-button-radius-icon" name="replay"  />
						</van-button>
						<!-- 播放/暂停 -->
						<van-button @click="playAudio" v-show="playAudioStatus === 0 || playAudioStatus === 2" class="my-button-radius my-button-radius-play" round type="default">
							<van-icon class="my-button-radius-icon" name="play-circle-o"  />
						</van-button>
						<van-button @click="pauseAudio" v-show="playAudioStatus === 1" class="my-button-radius my-button-radius-pause" round type="default">
							<van-icon class="my-button-radius-icon" name="pause-circle-o"  />
						</van-button>
						<!-- 停止播放 -->
						<van-button @click="stopAudio" :disabled="playAudioStatus === 0" class="my-button-radius my-button-radius-stop" round type="default">
							<van-icon class="my-button-radius-icon" name="stop-circle-o"  />
						</van-button>
					</view>
					<view class="my-view-hr-enter-containner">
						<view class="my-view-hr-enter"></view>
					</view>
					<view class="my-button-popup-enter-containner">
						<van-button @click="removeTempFile" class="my-button-popup-enter my-button-popup-enter-delete" color="linear-gradient(to right, #d5d5d5, #c3c3c3)">删除</van-button>
						<van-button @click="saveAudioFile" class="my-button-popup-enter my-button-popup-enter-save" color="linear-gradient(to right, #4bb0ff, #6149f6)">保存</van-button>
					</view>
				</view>
			</van-popup>
		</view>
	</view>
</template>

<script>
	export default {
		name: "Home",
		options: {
		    styleIsolation: 'shared', //微信开发，共享样式、样式穿透需要开启的属性
		},
		data() {
			return {
				currentTime: '00:00:00', 		//录音时长
				status: 0, 						//录音状态，0 停止，1 开始，2 暂停
				countTime: 0, 					//计时器 (单位 ms)
				intervalInstance: null, 		//计时器对象
				showBottomPopupView: false,		//弹出保存音乐界面
				showBottomPopupInputView: false,
				tagList: [],					//标记列表
				tempFilePath: null,				//临时存录音完成的路径
				playAudioStatus: 0, 			//播放录音，0 停止，1 开始，2 暂停
				innerAudioContext: null,		//播放音频上下文对象 (懒加载)
			};
		},
		created() {
			this.reset() //解决热启动隐患缓存 BUG
			this.initListener()
		},
		destroyed() { //释放资源，停止录音
			console.log('释放资源中......')
			this.reset()
		},
		methods: {
			initListener() { //初始化监听器
				var rm = uni.getRecorderManager()
				rm.onStart(res => {
					console.log('Listener 录音开始')
					this.reset() //每次开始前重置所有状态
					this.status = 1
					this.startTime()
				})
				rm.onPause(res => {
					console.log('Listener 录音暂停')
					this.status = 2
					this.clearIntervalInstance()
				})
				rm.onResume(res => {
					console.log('Listener 录音继续')
					this.status = 1 //更改为运行状态
					this.startTime()
				})
				rm.onStop(res => {
					this.tempFilePath = res.tempFilePath
					this.clearIntervalInstance()
					this.status = 0
					console.log('Listener 录音成功: ' + this.tempFilePath)
					this.popupBottomPopupView()
				})
				rm.onError(res => { //用于重置数据
					console.log('Listener 录音异常终止 : Reset Date ')
					this.reset()
				})
			},
			/**
			 * 重置数据, 当一些录音结束，或者关联的数据，请放到此处执行
			 */
			reset() { //重置数据
				this.clearIntervalInstance() //先结束异步任务
				this.currentTime = '00:00.00'
				this.status = 0
				this.countTime = 0 //重置计数器
				this.tagList = []
			},
			start() {
				if (this.status === 0) { //只有为初始状态才能开始录音
					console.log('录音开始')
					uni.getRecorderManager().start({
						duration: 600000, //最大录音时长，微信限制 10 分钟 (单位 ms)
						sampleRate: 44100, //采样率
						encodeBitRate: 320000, //编码率
						numberOfChannels: 1, //录音通道
						format: 'mp3' //格式
					})
				} else if (this.status === 2) { //暂停状态时，继续录音
					this.resume()
				} else {
					
				}
			},
			pause() {
				if (this.status === 1) { //当状态为已经是运行录音状态才能暂停
					console.log('录音暂停')
					uni.getRecorderManager().pause()
				} else {

				}
			},
			resume() {
				if (this.status === 2) { //当状态为暂停时才能继续录音
					console.log('录音继续')
					uni.getRecorderManager().resume()
				} else {

				}
			},
			stop() {
				if (this.status === 0) return
				if (this.status > 0) { //当状态为已经是运行录音状态才能停止录音
					console.log('录音停止')
					uni.getRecorderManager().stop()
				} else {

				}
			},
			tag() {
				if (this.status === 0) return
				if (this.tagList.length > 0 && this.tagList[0] === this.currentTime) {
					return
				}
				this.tagList.unshift(this.currentTime)
			},
			removeTag(index) {
				this.tagList.splice(index, 1)
			},
			startTime() {
				if (this.intervalInstance == null) { //为 null 时才执行，不为空代表任务还在执行
					this.intervalInstance = setInterval(() => {
						const i = 10 //固定值 i 递增 ms 单位时间
						const maxTime = 600000 //不能大于10分钟 (微信API规定，自动触发停止录音)
						if (this.countTime + i > maxTime) {
							return
						}
						var time = this.countTime += i
						//毫秒单位计算
						var m = Math.floor(time / 1000 / 60 % 60)
						var s = Math.floor(time / 1000 % 60)
						var c = Math.floor(time / i % 100)
						var strTime = this.fromCountTime(m) + ':' + this.fromCountTime(s) + '.' + this.fromCountTime(c)
						this.currentTime = strTime //更新
					}, 10) // -----> 每单位毫秒执行一次
				}
			},
			clearIntervalInstance() {
				if (this.intervalInstance) {
					clearInterval(this.intervalInstance) //清除
					this.intervalInstance = null //置空
				}
			},
			fromCountTime(v) { //格式化 00:00:00 的时分秒在某个块中的长度，一个长度则插入前导0，否则无需
				return ('' + v).length < 2 ? '0' + v : v
			},
			popupBottomPopupView() {
				this.showBottomPopupInputView = true
				this.showBottomPopupView = true
			},
			hideBottomPopupView() {
				this.showBottomPopupView = false
				this.resetPlayData()
			},
			resetPlayData() { //重置弹出框组件数据
				this.tempFilePath = null //置空源数据缓存
				this.playAudioStatus = 0
				if (this.innerAudioContext) {
					this.innerAudioContext.destroy() //根据官方文档，释放资源避免内存泄漏
					this.innerAudioContext = null //置空
				}
			},
			removeTempFile() { //仅模拟删除，并非真实删除 (小程序限制)
				this.hideBottomPopupView()
			},
			initAudioContext() { //初始化录音实例(注意这里未设置播放源数据)
				if (!this.innerAudioContext) {
					var audio = wx.createInnerAudioContext()
					this.innerAudioContext = audio
					audio.src = this.tempFilePath //注意要提前创建播放音频实例后再进行之后操作，不然有BUG
					audio.onPlay(() => {
						console.log('播放录音');
					})
					audio.onEnded(() => {
						console.log('onEnded 自动播放结束');
						this.playAudioStatus = 0
					})
					audio.onStop(() => {
						console.log('onStop 手动播放结束');
					})
					audio.onError((errMsg) => {
						console.log('播放失败', errMsg);
					})
				}
			},
			playAudio() {
				if (this.playAudioStatus === 1) return
				this.initAudioContext()
				this.innerAudioContext.play()
				this.playAudioStatus = 1
			},
			pauseAudio() {
				if (this.playAudioStatus !== 1) return
				this.innerAudioContext.pause()
				this.playAudioStatus = 2
			},
			stopAudio() {
				if (this.playAudioStatus === 0) return
				this.innerAudioContext.stop()
				this.playAudioStatus = 0
			},
			resetAudio() {
				this.stopAudio()
				this.playAudio()
			},
			saveAudioFile() {
				if (this.$refs.inputAudioFileName.value === '') return
				console.log(this.$refs.inputAudioFileName.value)
				//手动格式化日期
				const currentDate = new Date()
				const year = currentDate.getFullYear()
				const month = String(currentDate.getMonth() + 1).padStart(2, '0') // 月份从0开始，需要加1
				const day = String(currentDate.getDate()).padStart(2, '0')
				const formattedDate = `${year}/${month}/${day}`
				// const hours = String(currentDate.getHours()).padStart(2, '0')
				// const minutes = String(currentDate.getMinutes()).padStart(2, '0')
				// const seconds = String(currentDate.getSeconds()).padStart(2, '0')
				// const formattedTime = `${hours}:${minutes}:${seconds}` //00:00:00
				this.$store.commit('pushAudioFile', {
					name: this.$refs.inputAudioFileName.value, //通过引用的方式直接获取，双向绑定有BUG
					time: this.currentTime,
					date: formattedDate,
					tempFilePath: this.tempFilePath
				})
				this.hideBottomPopupView()
			},
			popupViewHideListener() {
				this.showBottomPopupInputView = false
				console.log('触发底部弹窗消失')
			}
		}
	}
</script>

<!-- 显示时间部分 -->
<style scoped>
.container-top-time {
	width: 100vw;
	margin-top: 400rpx;
	margin-bottom: 10rpx;
	display: flex;
	justify-content: center;
}
.content-top-time {
	font-size: 120rpx;
}
</style>

<!-- 标记列表 -->
<style scoped>
.container-tag-list {
	width: 100vw;
	display: flex;
	justify-content: center;
}
.content-tag-list {
	width: 450rpx;
	height: 300rpx;
	background-color: white;
	text-align: center;
	font-size: 30rpx;
}
.content-tag-item {
	width: 100%;
	margin-top: 15rpx;
	margin-bottom: 15rpx;
	display: flex;
}
.content-tag-item-child-index {
	flex: 1;
}
.content-tag-item-child-time {
	flex: 3;
}
.content-tag-item-child-remove {
	flex: 1;
}
</style>

<!-- 录音组件 -->
<style scoped>
.container-play-component {
	width: 100vw;
	margin-top: 30rpx;
	display: flex;
	justify-content: center;
	align-items: center;
}
.container-play-component >>> .van-button__text {
	font-size: 60rpx;
	color: white;
	background-color: rgba(0, 0, 0, 0);
}
.container-play-component >>> button {
	width: 150rpx;
	height: 150rpx;
	border-radius: 50%;
	margin-left: 30rpx;
	margin-right: 30rpx;
	background-color: gray;
}
.my-button-play-component-main >>> button {
	width: 188rpx;
	height: 188rpx;
	background-color: red;
}
.my-button-play-component-main >>> button .van-button__text {
	font-size: 80rpx;
}
.my-button-play-component-save >>> button {
	background-color: green;
}
</style>

<!-- 底部弹窗 -->
<style scoped>
.popup-bottom {
	width: 100%;
	height: 600rpx;
	background-color: white;
}
.popup-save-title {
	width: 100%;
	height: 100rpx;
	box-shadow: 0rpx 0rpx 10rpx 3rpx rgba(0, 0, 0, 0.5);
	display: flex;
	align-items: center;
	justify-content: center;
	text-align: center;
	font-size: 30rpx;
	color: black;
	margin-bottom: 30rpx;
}
.my-field {
	
}
.my-field >>> .van-cell  {
	width: 95%;
	height: 90rpx;
	margin: 0 auto;
	margin-bottom: 30rpx;
	padding-top: 5rpx;
	padding-bottom: 5rpx;
	border-radius: 25rpx;
	display: flex;
	align-items: center;
	justify-content: center;
	text-align: center;
    background: linear-gradient(to right, #efefef, #ebebeb);
}
.my-field >>> .van-icon.van-icon-smile-o {
	font-size: 55rpx;
	color: black;
}
.my-field >>> .van-icon {
	font-size: 40rpx;
}
.my-field >>> .van-field__label, .my-field >>> input {
	font-size: 30rpx;
}
.my-field >>> .van-field__placeholder {
	
}
.my-field >>> input {
	
}
</style>

<!-- 底部弹窗的播放按钮 -->
<style scoped>
.popup-bottom-play-container {
	width: 100%;
	display: flex;
	justify-content: center;
}
.my-button-radius {
	margin: 0 20rpx;
}
.my-button-radius >>> .van-button--round {
	border-radius: 50%;
	width: 150rpx;
	height: 150rpx;
}
.my-button-radius-replay >>> .van-button--round {
	background-color: grey;
}
.my-button-radius-play >>> .van-button--round {
	background-color: green;
}
.my-button-radius-stop >>> .van-button--round, 
.my-button-radius-pause >>> .van-button--round {
	background-color: red;
}
.my-button-radius-icon >>> .van-icon.van-icon-replay, 
.my-button-radius-icon >>> .van-icon.van-icon-play-circle-o, 
.my-button-radius-icon >>> .van-icon.van-icon-pause-circle-o, 
.my-button-radius-icon >>> .van-icon.van-icon-stop-circle-o {
	font-size: 55rpx;
	color: white;
}
</style>

<!-- 底部弹窗保存与删除按钮 -->
<style scoped>
.my-view-hr-enter-containner {
	width: 100%;
	display: flex;
	justify-content: center;
	margin-top: 30rpx;
	margin-bottom: 30rpx;
}
.my-view-hr-enter {
	width: 95%;
	height: 1px;
	background-color: rgba(0, 0, 0, 0.5);
}
.my-button-popup-enter-containner {
	width: 100%;
	display: flex;
	justify-content: center;
}
.my-button-popup-enter >>> .van-button.van-button--default.van-button--normal {
	width: 200rpx;
	height: 100rpx;
	margin-left: 80rpx;
	margin-right: 80rpx;
	color: white;
	font-size: 30rpx;
	font-style: normal;
	border-radius: 10%;
}
.my-button-popup-enter-save >>> .van-button.van-button--default.van-button--normal {
	background-color: rgba(0, 123, 255, 1.0);
}
.my-button-popup-enter-delete >>> .van-button.van-button--default.van-button--normal {
	background-color: grey;
}
</style>